#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "EasyXMen_sm2.h"
#include "EasyXMen_sm3.h"

int main()
{
	/* Declare three integer variables: rlen, slen, and rv. RLEN and SLEN are used to store the
	 *length of the R and S values obtained during the signing process, and RV is used to store the verification results*/
	int rlen, slen, rv;

	/*unsigned char digest_sm2[] = { 0x38,0x54,0xC4,0x63,0xFA,0x3F,0x73,0x78,0x36,0x21,0xB1,0xCE,0x4E,0xF8,0x3F,0x7C,0x78,0x04,0x8A,0xAC,0x79,0xB2,0x21,0xFC,0xDD,0x29,0x08,0x66,0xCC,0x13,0x11,0x74 };*/
	unsigned char kA_sm2[] = {0xBF, 0x72, 0x24, 0x72, 0x6B, 0xCF, 0x10, 0x2D, 0xF8, 0x55, 0x91, 0x52, 0x46, 0xB1, 0x13, 0x65, 0x5B, 0x39, 0x76, 0xF4, 0xD2, 0xA4, 0xD8, 0x49, 0x7A, 0x14, 0xAD, 0xD5, 0x0D, 0x82, 0xF2, 0x9C}; // Declare and initialize an array of unsigned char called kA_sm2, which contains the private key from the SM2 algorithm.

	// unsigned char r_sm2[] = { 0x6E,0x5D,0xB4,0x9D,0xBD,0x09,0x92,0xB9,0x70,0x40,0x08,0x0A,0x96,0x00,0x3C,0x72,0x1C,0xDB,0x9C,0xF6,0x4C,0x88,0xD7,0x43,0x21,0xFC,0x2F,0x63,0x0A,0xDF,0x37,0x74 };
	// unsigned char s_sm2[] = { 0x2F,0x6D,0xFF,0x45,0x3D,0xFC,0x8D,0x7A,0x50,0x6D,0x3F,0x52,0x30,0x1B,0xEE,0x52,0x9E,0x62,0xFD,0xDD,0x38,0x94,0x8F,0x0D,0x5D,0x2C,0xBC,0xBC,0x55,0x90,0x0C,0xFA };
	unsigned char r_sm2[32];
	/*Declare two unsigned char arrays named r_sm2 and s_sm2 that will be used to
	 *store the R and S values obtained during the signing process.*/
	unsigned char s_sm2[32];

	clock_t start, end;
	double tt;
	/*Declare the variables start and end for timing, as well as TT and loop counter j for calculating time.*/
	int j;

	/*Set the number of cycles to 200 to test the speed of signing and verification.*/
	int loop = 200;
	/*Declare a user ID string and calculate its length (excluding the null characters at the end).	*/
	unsigned char userid[] = "1234567812345678";
	int userid_len = sizeof(userid) - 1;
	unsigned char xa[] = {0x50, 0xE2, 0x78, 0xAB, 0xBA, 0xB4, 0x5C, 0xA2, 0xE8, 0x13, 0x41, 0x99, 0xE0, 0xED, 0xE0, 0xCA, 0xA6, 0x94, 0xD3, 0xDE, 0x26, 0xC9, 0xFC, 0xEF, 0xFC, 0xDF, 0xEE, 0xDC, 0x85, 0x92, 0xCC, 0x9D};
	int xa_len = sizeof(xa);
	unsigned char ya[] = {0x4E, 0x6E, 0xDE, 0x36, 0x2A, 0x2C, 0x62, 0x47, 0xA1, 0x56, 0x33, 0x63, 0x84, 0xDC, 0x9C, 0x09, 0xE3, 0x6B, 0x14, 0xB5, 0x63, 0x9B, 0xEB, 0xDD, 0x1B, 0x99, 0xC9, 0x2A, 0x4E, 0x46, 0x44, 0xCD};
	/*Declare and initialize two arrays, xa and ya, which contain the public key
	 *coordinates in the SM2 algorithm, and calculate their lengths.*/
	int ya_len = sizeof(ya);
	unsigned char msg[] = {0x7C, 0x93, 0xAA, 0x2C, 0xB2, 0x89, 0xD3, 0x63, 0x94, 0x53, 0xCE, 0x12, 0x40, 0x8F, 0x81, 0x29, 0x53, 0x33, 0x52, 0x8D, 0x04, 0x81, 0x16, 0x3C, 0x76, 0xC9, 0x2C, 0x2E, 0xD5, 0xA2, 0x8F, 0x48, 0x46, 0xE6, 0x3B, 0xC4, 0x6A, 0x17, 0xAD, 0x1F, 0x89, 0x4D, 0x48, 0xF7, 0x1A, 0xDD, 0x66, 0x1C, 0x00, 0x52, 0x9B, 0x96, 0x1C, 0x6D, 0x86, 0xE7, 0xB4, 0xB0, 0xE6, 0x02, 0x46, 0xF0, 0xD8, 0x14, 0x10, 0x07, 0x62, 0xAC, 0xA1, 0x5F, 0x89, 0xC7, 0x81, 0x26, 0xC5, 0x4A, 0xC7, 0xCB, 0xF7, 0x42, 0x39, 0x1B, 0x65, 0xC7, 0x0C, 0x9D, 0x82, 0x7E, 0xB9, 0x9C, 0x33, 0xAE, 0x14, 0xF6, 0xD2, 0x66, 0x0A, 0x80, 0xD3, 0xCD, 0xB3, 0x72, 0xD1, 0x42, 0xD4, 0xC9, 0xFD, 0x15, 0x8D, 0x77, 0x22, 0xF8, 0x1C, 0x74, 0x41, 0x21, 0x3A, 0xF3, 0x15, 0x9C, 0x53, 0x41, 0x7D, 0x10, 0x69, 0x2F, 0xD6, 0x04, 0x3A, 0x79, 0x2C, 0xA6, 0x6C, 0xBD, 0x01, 0x4A, 0xE0, 0xCE, 0xC7, 0x69, 0x18, 0xF7, 0x74, 0xF4, 0xEB, 0xA7, 0x50, 0xD6, 0x8F, 0x88, 0xD5, 0x41, 0x3D, 0x54, 0xAE, 0x08, 0xC9, 0xB1, 0xA8, 0xF7, 0xD7, 0xA6, 0x1B, 0x9C, 0x59, 0xE1, 0x63, 0xA1, 0x4D, 0x9B, 0xF9, 0x9F, 0x47, 0x20, 0x13, 0xC2, 0xE6, 0xE2, 0xE7, 0x6F, 0xD8, 0x85, 0xB6, 0x82, 0xB1, 0x35, 0xD9, 0x0F, 0x2F, 0x49, 0x45, 0xE9, 0x94, 0x89, 0xAA, 0x80, 0x7F, 0xDD, 0x8D, 0x24, 0x74, 0x5B, 0x26, 0x23, 0xC2, 0x53, 0xBF, 0x55, 0xC3, 0xDE, 0x6A, 0x91, 0xA6, 0x12, 0xA5, 0x97, 0x90, 0x90, 0xEF, 0x7D, 0x80, 0x4D, 0x04, 0x51, 0xEA, 0x5A, 0x2B, 0x1F, 0x23, 0xA3, 0xE9, 0x72, 0x04, 0x24, 0x6F, 0xB3, 0xFE, 0xFE, 0xCB, 0xF1, 0xBC, 0xEF, 0xA4, 0x2F, 0x44, 0x7D, 0xA2, 0x63, 0x28, 0x9C, 0x84, 0x85, 0x6A, 0x3E, 0xD5, 0xDC, 0xBE, 0xBB, 0xEA, 0x1C, 0x9F, 0xF9, 0x86, 0xC0, 0xB4, 0x45, 0x08, 0xEB, 0x8B, 0x04, 0x30, 0x9F, 0x72, 0x28, 0xA8, 0xBE, 0x63, 0xD3, 0x21, 0x2D, 0xAA, 0x17, 0xC7, 0xE8, 0xE2, 0xEE, 0x76, 0x44, 0xC5, 0xF3, 0x1B, 0x7A, 0xCD, 0x7A, 0xF4, 0xE9, 0x8C, 0x03, 0xBA, 0xB7, 0x54, 0xB7, 0xCC, 0x74, 0x26, 0x41, 0xBB, 0xA7, 0x3E, 0x39, 0x7D, 0x3B, 0x82, 0x8B, 0x1C, 0xA2, 0x0C, 0x74, 0x97, 0x27, 0xBD, 0x3B, 0xDC, 0x45, 0xAC, 0xEE, 0xC1, 0x8B, 0x82, 0xD4, 0x76, 0xAA, 0x27, 0xED, 0x36, 0xA6, 0x12, 0x95, 0xAD, 0x91, 0x4E, 0x0A, 0x69, 0xED, 0x24, 0x72, 0x6F, 0xDF, 0x2D, 0xF6, 0x3A, 0x1D, 0x7E, 0xA8, 0x99, 0x75, 0x58, 0xCA, 0x9D, 0xD9, 0xC4, 0x4E, 0x15, 0xF1, 0xF4, 0x0B, 0x50, 0x61, 0xA2, 0x9F, 0xA7, 0xE4, 0x3B, 0xD8, 0x7F, 0x47, 0x06, 0x9D, 0x42, 0x06, 0x75, 0xC8, 0x4B, 0x8C, 0xA5, 0x03, 0x7C, 0x20, 0xBA, 0x17, 0x59, 0xCC, 0x3F, 0x82, 0x24, 0x39, 0x2B, 0x3B, 0xF5, 0x86, 0xBB, 0x42, 0x9A, 0x38, 0x83, 0x0C, 0xB8, 0x19, 0x15, 0x50, 0x31, 0x2A, 0xDB, 0xBF, 0x12, 0xB1, 0x8F, 0x53, 0x7D, 0x3F, 0xC5, 0xF4, 0x0E, 0xF6, 0xF4, 0xD7, 0x2A, 0x2F, 0x42, 0x45, 0xAE, 0x3F, 0x30, 0xF2, 0x65, 0x4E, 0xB4, 0xC5, 0xC6, 0x8F, 0x52, 0x76, 0x12, 0xD9, 0x76, 0xD9, 0x01, 0xB7, 0xBD, 0x8A, 0xEB, 0x5E, 0x8E, 0x90, 0x71, 0xB9, 0x1C, 0x22, 0xA3, 0x03, 0x95, 0x31, 0xA3, 0xBC, 0xE0, 0xFF, 0x1D, 0x8D, 0xF5, 0x55, 0x42, 0xAF, 0x9D, 0x2D, 0x14, 0x75, 0x52, 0xE5, 0x77, 0x1C, 0x38, 0x79, 0xE4, 0x40, 0x7B, 0x0E, 0x86, 0xFD, 0x30, 0x12, 0xBD, 0xFA, 0x72, 0x5E, 0x3B, 0xDD, 0x42, 0x33, 0xF8, 0xEA, 0x2A, 0x91, 0x4D, 0x00, 0x06, 0xDC, 0x93, 0xD8, 0x32, 0xDE, 0x11, 0xC7, 0x06, 0x0E, 0xB2, 0xD9, 0xF9, 0x0C, 0xAE, 0x50, 0x26, 0x72, 0xEF, 0x8E, 0xAC, 0x2A, 0x31, 0xBD, 0x3B, 0x35, 0x94, 0x23, 0x0C, 0xAA, 0x92, 0xDB, 0x6D, 0x00, 0x66, 0xFF, 0xA6, 0xC2, 0xA8, 0xE2, 0x0E, 0xF5, 0x6E, 0x26, 0x95, 0xEE, 0x5B, 0xC0, 0x17, 0xD1, 0x8A, 0x4F, 0x00, 0xA6, 0x8F, 0x4C, 0x26, 0x0B, 0xD6, 0x72, 0xE2, 0xC5, 0xB8, 0xDF, 0x4C, 0xBB, 0x70, 0xC6, 0x4A, 0x5E, 0x03, 0x03, 0x2E, 0x50, 0xAB, 0x9E, 0x99, 0x7A, 0x0F, 0x1F, 0xB0, 0xC4, 0x98, 0x32, 0x8E, 0xA6, 0xE7, 0x85, 0x6A, 0x3F, 0xFB, 0xBA, 0x5F, 0x46, 0x77, 0x45, 0xDB, 0xE1, 0x46, 0x0E, 0xA7, 0x85, 0xC6, 0x1B, 0x4B, 0x07, 0xFE, 0x39, 0xE6, 0x61, 0xA5, 0xB8, 0xF6, 0x2C, 0x14, 0x5E, 0x53, 0x4E, 0xFF, 0x7D, 0x06, 0xCC, 0x34, 0x3A, 0x6D, 0x49, 0xDF, 0x0C, 0xB2, 0x05, 0x7D, 0x41, 0x89, 0x7C, 0x02, 0x4A, 0x1F, 0xBC, 0xA4, 0x85, 0x75, 0x53, 0xED, 0x49, 0x8D, 0xEA, 0xCF, 0x19, 0x23, 0xF0, 0xA2, 0xA8, 0x15, 0x5F, 0xAB, 0x0A, 0xC5, 0xCB, 0x2C, 0x78, 0x37, 0x17, 0x0E, 0x08, 0x71, 0xDF, 0x48, 0x95, 0xC1, 0xD0, 0x03, 0x2D, 0xF7, 0x88, 0x1F, 0x0C, 0x5F, 0x2B, 0xD4, 0x93, 0x22, 0x3F, 0x73, 0xBA, 0x21, 0x46, 0x5F, 0xE3, 0x43, 0x44, 0xFF, 0x70, 0x5C, 0x88, 0xF5, 0xA7, 0xCE, 0x9D, 0x99, 0x7E, 0x21, 0xCD, 0x36, 0x5D, 0x21, 0xBB, 0x59, 0xF5, 0xB6, 0xB8, 0xA8, 0x9C, 0x49, 0xEE, 0x7A, 0x8C, 0x68, 0xA9, 0x3F, 0x43, 0xCD, 0xC6, 0x9C, 0xF7, 0xA9, 0xBC, 0x61, 0xEB, 0x32, 0x25, 0x64, 0x8E, 0x5B, 0x4D, 0x90, 0xAB, 0x13, 0x6D, 0x82, 0x59, 0xD3, 0xB0, 0x60, 0x6F, 0xC0, 0xB4, 0x8F, 0x6A, 0xCC, 0x0F, 0xE2, 0x32, 0x32, 0x3F, 0x21, 0xD1, 0x37, 0xE8, 0xC9, 0x06, 0xBE, 0x5F, 0xDC, 0xC7, 0x34, 0x01, 0xC2, 0x23, 0x4C, 0xC4, 0x95, 0x5E, 0xD9, 0xEA, 0x3D, 0x19, 0x06, 0x60, 0x5D, 0xAC, 0x78, 0x8E, 0xFF, 0x8A, 0x86, 0x49, 0xE8, 0xCE, 0x0B, 0x88, 0x7E, 0x58, 0x16, 0x4D, 0xB6, 0xFF, 0x5C, 0x23, 0xA9, 0x51, 0x77, 0xE6, 0x2D, 0x50, 0x4D, 0x6C, 0x15, 0x8A, 0x3F, 0x39, 0xF4, 0x05, 0x87, 0xA3, 0x17, 0xFD, 0xD6, 0x3E, 0x1D, 0xC6, 0x98, 0x22, 0x2C, 0xA1, 0xCF, 0x59, 0x01, 0xB9, 0xF8, 0xBF, 0xE2, 0xE5, 0xB3, 0x73, 0xDD, 0x2E, 0xBC, 0xCC, 0xA7, 0xFD, 0x8C, 0x1D, 0x58, 0xB9, 0xDF, 0x5B, 0x7D, 0xBE, 0xC2, 0x50, 0x09, 0x81, 0x44, 0xDC, 0xC7, 0x59, 0x56, 0x3F, 0xCA, 0x64, 0x67, 0x4D, 0x75, 0xA6, 0x52, 0x4F, 0x6F, 0x7E, 0x8D, 0xAD, 0x58, 0x70, 0x95, 0x3C, 0x6D, 0xD1, 0x1E, 0x0F, 0xD7, 0x36, 0x80, 0xC8, 0x37, 0x90, 0x8F, 0xF0, 0x7A, 0x95, 0xD8, 0x91, 0xC1, 0x51, 0xD8, 0xF4, 0xF5, 0xC8, 0x4C, 0x26, 0xEC, 0xD6, 0x72, 0xD2, 0xE5, 0xB3, 0x90, 0xE3, 0x35, 0xCB, 0xF2, 0x58, 0x55, 0xC2, 0x3B, 0x15, 0xBC, 0x34, 0x48, 0xBD, 0x91, 0x6E, 0xF2, 0x15, 0x28, 0xA4, 0x57, 0xC3, 0x79, 0x5F, 0x98, 0x5A, 0xF1, 0x86, 0x76, 0x85, 0x09, 0x65, 0x04, 0xC8, 0x7B, 0x60, 0xE7, 0x57, 0x4E, 0x04, 0xA6, 0xE0, 0xE5, 0x46, 0x58, 0x8F, 0x47, 0x1E, 0x3B, 0x77, 0xB2, 0xD4, 0x69, 0x00, 0x30, 0x29, 0x8D, 0x67, 0xFD, 0xEA, 0x7C, 0x52, 0xCE, 0x2F, 0xEC, 0x54, 0xAE, 0xFB, 0x4F, 0xFB, 0x59, 0x81, 0xAB, 0x44, 0xCC, 0xD1, 0x96, 0xC2, 0xE0, 0x19, 0x20, 0x53, 0xFC, 0x6A, 0x01, 0xEB, 0x37, 0x2E, 0x61, 0xFB, 0xA5, 0xEA, 0xE2, 0x6A, 0x4F, 0x2E, 0x32, 0xD2, 0x95, 0xDA, 0xDF, 0x18, 0x9F, 0xED, 0xD1, 0x4A, 0x1F, 0x03, 0xC5, 0x68, 0xB3, 0xD1, 0x2C, 0x09, 0xE9, 0x27, 0x00};

	/*Declare and initialize an array called msg, which contains the message to be signed, and calculates its length.*/
	int msg_len = sizeof(msg) - 1;
	/*digest*/
	unsigned char e[32];

	/*Call the EasyXMen_sm3Hash function, pass in the user ID, public key coordinates,
	 *and message, and calculate the hash value (summary) of the message.*/
	int ret = EasyXMen_sm3Hash(userid, userid_len, xa, xa_len, ya, ya_len, msg, msg_len, e);
	if (ret == 0)
	{
		printf("Hash (e): ");
		for (int i = 0; i < 32; i++)
		{
			printf("%02X", e[i]);
		}
		printf("\n");
	}
	else
	{
		/*If the hash calculation is successful, the calculated summary is output; If it fails, an error message is output.*/
		printf("Failed to compute hash.\n");
	}

	/*Record the start time.*/
	start = clock();

	for (j = 0; j < loop; j++)
		/*Loop 200 times, call the EasyXMen_sm2_sign function to sign.*/
		EasyXMen_sm2_sign(e, 32, kA_sm2, 32, r_sm2, &rlen, s_sm2, &slen);

	/*Record the end time.*/
	end = clock();
	/*Calculate the total time for the signature operation.*/
	tt = (double)(end - start) / CLOCKS_PER_SEC;
	int len = sizeof(s_sm2) / sizeof(s_sm2[0]);
	/*Calculate the length of r_sm2 and s_sm2 arrays.*/
	int len1 = sizeof(r_sm2) / sizeof(r_sm2[0]);
	printf("rr:\n");
	for (int i = 0; i < len; i++)
	{
		/*The S values of the signature are output*/
		printf("%02X ", r_sm2[i]);
	}

	printf("ss:\n");
	for (int i = 0; i < len; i++)
	{
		/*The  S values of the signature are output*/
		printf("%02X ", s_sm2[i]);
	}
	/*Calculate the signature speed.*/
	printf("sm2_sign speed:%lf/s\n", (double)j / tt);
	start = clock();

	for (j = 0; j < loop; j++)
		rv = EasyXMen_sm2_verify(e, 32, r_sm2, 32, s_sm2, 32, xa, 32, ya, 32);
	/*Loop 200 times and call the EasyXMen_sm2_verify function for signature verification.*/
	end = clock();
	/*The end time is recorded, and the total time for the validation operation is calculated.*/
	tt = (double)(end - start) / CLOCKS_PER_SEC;

	/*Output verification speed.*/
	printf("sm2_verify speed:%lf/s\n", (double)j / tt);
	if (rv != 0)
		printf("sm2_verify error!===%d\n", rv);
	else
		/*Determine whether the verification is successful based on the return value and output the corresponding information.*/
		printf("sm2_verify OK!===%d\n", rv);

	/*Test case for testing SM2 signature verification negative response:
	Modify the generated signature and then perform signature verification, the result should be verification failure.*/
	r_sm2[20] = 1;
	s_sm2[10] = 254;
	rv = EasyXMen_sm2_verify(e, 32, r_sm2, 32, s_sm2, 32, xa, 32, ya, 32);
	if (rv != 0)
		printf("sm2_verify error!===%d\n", rv);
	else
		printf("sm2_verify OK!===%d\n", rv);

	return 0;
}
